/*
 * TicTacToePanel.java
 *
 * Created on February 6, 2005, 6:28 AM
 */

package net.jxta.myjxta.plugins.tictactoe;


import info.clearthought.layout.TableLayout;
import net.jxta.logging.Logging;
import net.jxta.myjxta.View;
import net.jxta.myjxta.dialog.Dialog;
import net.jxta.myjxta.plugin.PluginView;
import net.jxta.myjxta.util.Resources;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Jeff Moore
 */
public final class TicTacToeDialogView extends JPanel implements PluginView {

    private final int gridRows = 3;

    private final int gridColumns = 3;

    private static final String NO_RESPONSE_PANEL = "noResponsePanel";

    private static final String CONFIG_CHOOSE_ICON_PANEL = "configChooseIconPanel";

    public static final String ICON_TYPE_CUSTOM = "IconTypeCustom";

    public static final String ICON_TYPE_X = "IconTypeX";

    public static final String ICON_TYPE_O = "IconTypeO";

    private final TicTacToeGridBox[][] grid = new TicTacToeGridBox[gridRows][gridColumns];

    private static final String CONFIG_PANEL = "ConfigPanel";

    private static final String GAME_CONTROL_PANEL = "gameControlPanel";

    private static final String ERROR_PANEL = "errorPanel";

    private final static String DISPLAY_LOCAL_PLAYERS_TURN = "Your Turn!";

    private final static String DISPLAY_REMOTE_PLAYERS_TURN = "'s Turn!";

    private final static String DISPLAY_SESSION_TTT_DISCONNECTED = "Disconnected";

    private final static String DISPLAY_SESSION_TTT_DISCONNECTING = "Disconnecting";

    private final static String DISPLAY_SESSION_TTT_ENDED = "Game Over";

    private final static String DISPLAY_SESSION_TTT_ENDING = "Game Ending...";

    private final static String DISPLAY_SESSION_TTT_STARTING = "Starting";

    private final static String DISPLAY_SESSION_TTT_STARTED = "Started";

    private final static String DISPLAY_SESSION_TTT_CONNECTED = "Connected";

    private final static String DISPLAY_SESSION_TTT_CONNECTING = "Connecting";


    private final static String GAME_DRAW = "Draw!!";

    private final static String GAME_WON = "Game Won!!";

    private final static String GAME_LOST = "Game Lost!!";

    private final int blinkVector = 8; //# times to blink

    private final int blinkRate = 250; // in milliseconds

    private JLabel localPlayerNameLabel = null;

    private JLabel remotePlayerNameLabel = null;

    private JLabel remotePlayerWinsLabel = null;

    private JLabel localPlayerWinsLabel = null;

    private ImageIcon localPlayerIcon = null;

    private ImageIcon remotePlayerIcon = null;

    private String localPlayerIconType = null;

    private String remotePlayerIconType = null;

    private JLabel productLabel = null;

    private JLabel errorMessageLabel = null;

    private JLabel protocolStateLabel = null;

    private JLabel messageLabel = null;

    private JLabel playersTurnLabel = null;

    private JLabel localPlayerIconLabel = null;

    private JLabel remotePlayerIconLabel = null;

    private JLabel customIconLabel = null;

    private JLabel currentIconLabel = null;

    private JLabel remoteIconLabel = null;

    private TicTacToeGameControl gameControl = null;

    private List<MoveListener> moveListeners = null;

    private ImageIcon iconX = null;

    private ImageIcon iconBlank = null;

    private ImageIcon iconO = null;

    private JLabel gameStateLabel = null;

    private CardLayout cardLayout = null;

    private CardLayout configCardLayout = null;

    private JPanel deckPanel = null;

    private JPanel configDeckPanel = null;

    private Dialog tttDialog = null;


    private JButton startGameButton = null;

    private JButton closeButton = null;

    private JButton playAgainButton = null;

    private String remotePlayerName = null;

    private String localPlayerName = null;

    private String localPlayerIconFileName = null;

    private final boolean m_isLocallyInitiated;

    static final Logger LOG = Logger.getLogger(TicTacToeDialogView.class.getName());

    /**
     * Creates a new instance of TicTacToePanel
     */
    public TicTacToeDialogView(View view, Dialog dialog, boolean locallyInitiated) {

        LOG.setLevel(Level.INFO);
        m_isLocallyInitiated = locallyInitiated;
        if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
            LOG.info("Contructor");

        }

        this.tttDialog = dialog;

        this.moveListeners = new ArrayList<MoveListener>();

        Resources res = Resources.getInstance();

        iconX = res.getIconResource("TicTacToe.X");

        iconO = res.getIconResource("TicTacToe.O");

        iconBlank = res.getIconResource("TicTacToe.BLANK");

        localPlayerName = this.tttDialog.getGroup().getPeerGroup().getPeerName();

        UI();


        gameControl = new TicTacToeGameControl(this, dialog);


        if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
            LOG.info("End constructor");

        }

        gameControl.initSession();

    }


    public Dialog getDialog() {
        return this.tttDialog;
    }

    public void dismiss() {
        this.destruct();
    }

    private void destruct() {

        if (getGameControl() != null) {
            getGameControl().destruct();
        }

        if (moveListeners != null) {
            moveListeners.clear();
        }


        gameControl = null;


        if (tttDialog != null) {


            this.tttDialog.close();
        }

        //myJxtaView.removeDialog (tttDialog);

    }

    private void updateMessageLabel(final String message) {


        if (messageLabel != null) {
            EventQueue.invokeLater(new Runnable() {


                public void run() {

                    messageLabel.setText(message);
                }
            });
        }
    }

    private void updateProtocolStateLabel(final String protocolState) {
        if (protocolStateLabel != null) {
            EventQueue.invokeLater(new Runnable() {


                public void run() {

                    protocolStateLabel.setText(protocolState);
                }
            });
        }
    }

    public void protocolStateChanged(int protocolState) {

        LOG.info("gameControl " + this.gameControl);
        LOG.info("getSessionString " +
                this.gameControl.getSessionStateString(protocolState));

        this.updateProtocolStateLabel(this.gameControl.getSessionStateString(protocolState));

        if (protocolState == TicTacToeGameControl.SESSION_INVITE_REQUEST_RECEIVED) {


            this.updateMessageLabel("Remote player Choosing Icon");


        } else if (protocolState == TicTacToeGameControl.SESSION_INVITE_ACCEPT_RECEIVED) {


            showPanel(CONFIG_PANEL);

            this.showConfigPanel(CONFIG_CHOOSE_ICON_PANEL);

            this.updateMessageLabel("Choose Your Icon");

        } else if (protocolState == TicTacToeGameControl.SESSION_CONFIG_ACCEPT_SENT) {

            this.updateMessageLabel("Starting...");

        } else if (protocolState == TicTacToeGameControl.SESSION_CONFIG_REQUEST_RECEIVED) {

            this.updateMessageLabel("Choose Your Icon");

            remoteIconLabel.setIcon(this.getRemotePlayerIcon());

            remotePlayerIconChosen();

            showPanel(CONFIG_PANEL);

            this.showConfigPanel(CONFIG_CHOOSE_ICON_PANEL);

        } else if (protocolState == TicTacToeGameControl.SESSION_CONFIG_REQUEST_SENT) {

            this.updateMessageLabel("Remote Player Choosing Icon");
        } else if (protocolState == TicTacToeGameControl.SESSION_CONFIG_ACCEPT_RECEIVED) {

            this.updateMessageLabel("SESSION_CONFIG_ACCEPT_RECEIVED (Remote Player has choosen Icon)");

        } else if (protocolState == TicTacToeGameControl.SESSION_START_REQUEST_SENT) {

            this.updateMessageLabel("SESSION_START_REQUEST_SENT ");

        } else if (protocolState == TicTacToeGameControl.SESSION_START_REQUEST_RECEIVED) {

            this.updateMessageLabel("Starting Game (session start request received)");

            showPanel(GAME_CONTROL_PANEL);

            resetGrid();


        } else if (protocolState == TicTacToeGameControl.SESSION_START_ACCEPT_RECEIVED) {

            this.updateMessageLabel("Starting Game (session start accepted)");

            showPanel(GAME_CONTROL_PANEL);

            resetGrid();

        } else if (protocolState == TicTacToeGameControl.SESSION_PLAYING) {

            updateGameStateView("Playing");


        } else if (protocolState == TicTacToeGameControl.SESSION_ENDED) {

            this.updateMessageLabel("Game Over");

            updatePlayersTurnView("");

            if (isLocallyInitiated()) {
                playAgainButton.setEnabled(true);
                playAgainButton.setVisible(true);
            }

        } else if (protocolState == TicTacToeGameControl.SESSION_END_REQUEST_RECEIVED) {
            this.updateMessageLabel("Game Ending");
        } else if (protocolState == TicTacToeGameControl.SESSION_DISCONNECT_REQUEST_RECEIVED) {
            this.updateMessageLabel("Disconnecting");
        } else if (protocolState == TicTacToeGameControl.SESSION_DISCONNECTED) {
            this.updateMessageLabel("Disconnected");


        } else {
            System.out.println("strange state"+protocolState+ " is local:"+this.getGameControl().isLocallyInitiated());
        }


    }


    private void remotePlayerIconChosen() {


    }

    private void UI() {

        this.setPreferredSize(new Dimension(440, 300));

        double sizes[][] = {{TableLayout.FILL}, {TableLayout.PREFERRED, TableLayout.FILL}};
        TableLayout tbl = new TableLayout(sizes);
        JPanel uiPanel = new JPanel(tbl);

        uiPanel.add(buildMessagePanel(), "0,0,l,c");

        cardLayout = new CardLayout();
        deckPanel = new JPanel(cardLayout);

        deckPanel.add(this.buildNoResponsePanel(), NO_RESPONSE_PANEL);

        deckPanel.add(this.buildConfigPanel(), CONFIG_PANEL);

        deckPanel.add(this.buildGamePanel(), GAME_CONTROL_PANEL);

        deckPanel.add(this.buildErrorPanel(), ERROR_PANEL);

        uiPanel.add(deckPanel, "0,1,c,c");

        showPanel(NO_RESPONSE_PANEL);

        this.add(uiPanel);
    }

    private JPanel buildErrorPanel() {

        double sizes[][] = {{TableLayout.PREFERRED},
                {TableLayout.PREFERRED, TableLayout.PREFERRED}};

        TableLayout tbl = new TableLayout(sizes);

        JPanel panel = new JPanel(tbl);

        errorMessageLabel = new JLabel("ERROR");

        panel.add(errorMessageLabel, "0,0");

        return panel;

    }


    private JPanel buildNoResponsePanel() {

        double sizes[][] = {{TableLayout.FILL},
                {TableLayout.FILL}};

        TableLayout tbl = new TableLayout(sizes);

        JPanel panel = new JPanel(tbl);


        return panel;
    }

    private JPanel buildMessagePanel() {

        double b = 5;
        double sizes[][] = {{b, TableLayout.FILL, b},
                {b, TableLayout.PREFERRED, b, TableLayout.PREFERRED, b, TableLayout.PREFERRED, b}};

        TableLayout tbl = new TableLayout(sizes);

        JPanel panel = new JPanel(tbl);

        productLabel = new JLabel("TicTacToe .01");
        //productLabel.setFont (new Font ("Arial", Font.BOLD, 14));
        productLabel.setForeground(new Color(0.0f, 0.0f, 0.0f, 0.5f));
        panel.add(productLabel, "1,1,l,c");

        protocolStateLabel = new JLabel("protocolState");
        panel.add(protocolStateLabel, "1,3,l,c");

        messageLabel = new JLabel("Message");
        messageLabel.setFont(new Font("Arial", Font.BOLD, 14));
        messageLabel.setForeground(new Color(0.0f, 0.0f, 0.0f));
        panel.add(messageLabel, "1,5,c,c");

        return panel;
    }

    private JPanel buildConfigPanel() {

        configCardLayout = new CardLayout();

        configDeckPanel = new JPanel(configCardLayout);

        configDeckPanel.add(buildConfigChooseIconPanel(), CONFIG_CHOOSE_ICON_PANEL);

        this.showConfigPanel(CONFIG_CHOOSE_ICON_PANEL);

        return configDeckPanel;

    }


    private JPanel buildGameStatusPanel() {

        double sizes[][] = {{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL},
                {TableLayout.PREFERRED}};
        TableLayout tbl = new TableLayout(sizes);
        JPanel panel = new JPanel(tbl);

        panel.setBorder(null);
        panel.setBackground(Color.WHITE);

        //game status label
        playAgainButton = new JButton("Play Again");
        panel.add(playAgainButton, "0,0, l , c");
        playAgainButton.setEnabled(false);
        playAgainButton.setVisible(false);
        playAgainButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                localActionPlayAgain();
            }
        });

        gameStateLabel = new JLabel("gameStateLabel");
        panel.add(gameStateLabel, "1,0,l,c");

        playersTurnLabel = new JLabel("Players Turn");
        panel.add(playersTurnLabel, "2,0,r,c");
        playersTurnLabel.setFont(new Font("Arial", Font.BOLD, 12));
        playersTurnLabel.setForeground(Color.BLACK);

        return panel;

    }

    private JPanel buildUpperInfoPanel() {

        double sizes[][] = {{TableLayout.FILL, TableLayout.FILL},
                {TableLayout.PREFERRED}};
        TableLayout tbl = new TableLayout(sizes);
        JPanel panel = new JPanel(tbl);
        panel.setBackground(Color.white);

        localPlayerNameLabel = new JLabel(this.localPlayerName);
        panel.add(localPlayerNameLabel, "0,0,l,c");
        localPlayerNameLabel.setFont(new Font("Arial", Font.BOLD, 18));
        localPlayerNameLabel.setForeground(Color.BLUE);

        remotePlayerNameLabel = new JLabel("remotePlayer");
        panel.add(remotePlayerNameLabel, "1,0,r,c");
        remotePlayerNameLabel.setFont(new Font("Arial", Font.BOLD, 18));
        remotePlayerNameLabel.setForeground(Color.BLUE);


        return panel;
    }

    private JPanel buildLowerInfoPanel() {

        double sizes[][] = {{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL},
                {TableLayout.FILL}};
        TableLayout tbl = new TableLayout(sizes);
        JPanel panel = new JPanel(tbl);
        panel.setBackground(Color.white);

        remotePlayerIconLabel = new JLabel();
        panel.add(remotePlayerIconLabel, "0,0,l,c");
        remotePlayerIconLabel.setIcon(this.iconBlank);

        JPanel statsPanel = buildGameStatsPanel();
        panel.add(statsPanel, "1,0,c,c");
        statsPanel.setBorder(null);

        localPlayerIconLabel = new JLabel();
        panel.add(localPlayerIconLabel, "2,0,r,c");
        localPlayerIconLabel.setIcon(this.iconBlank);

        return panel;
    }


    private JPanel buildGameInfoPanel() {

        double sizes[][] = {{TableLayout.FILL},
                {TableLayout.PREFERRED, TableLayout.FILL}};
        TableLayout tbl = new TableLayout(sizes);
        JPanel panel = new JPanel(tbl);
        panel.setBackground(Color.white);

        JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL);
        panel.add(separator, "0,0,2,0");

        panel.add(this.buildUpperInfoPanel(), "0,0");

        panel.add(this.buildLowerInfoPanel(), "0,1");

        return panel;
    }

    private JPanel buildGameStatsPanel() {

        double sizes[][] = {{TableLayout.FILL},
                {TableLayout.PREFERRED, TableLayout.PREFERRED}};
        TableLayout tbl = new TableLayout(sizes);
        JPanel panel = new JPanel(tbl);
        panel.setBackground(Color.white);
        panel.setBorder(null);

        double sizesLabel[][] = {{TableLayout.FILL},
                {TableLayout.PREFERRED, TableLayout.FILL}};
        TableLayout tblLabel = new TableLayout(sizesLabel);
        JPanel panelLabel = new JPanel(tblLabel);
        panel.add(panelLabel, "0,0,c,c");
        panelLabel.setBackground(Color.white);
        panelLabel.setBorder(null);

        double sizesData[][] = {{TableLayout.FILL, TableLayout.PREFERRED, TableLayout.FILL},
                {TableLayout.PREFERRED, TableLayout.PREFERRED}};
        TableLayout tblData = new TableLayout(sizesData);
        JPanel panelData = new JPanel(tblData);
        panel.add(panelData, "0,1");
        panelData.setBackground(Color.white);
        panelData.setBorder(null);

        //winsLabel
        JLabel winsLabel = new JLabel("WINS");
        panelLabel.add(winsLabel, "0,0,c,c");
        winsLabel.setFont(new Font("Arial", Font.PLAIN, 18));
        winsLabel.setForeground(Color.BLACK);

        //separator
        JSeparator separatorH = new JSeparator(SwingConstants.HORIZONTAL);
        panelLabel.add(separatorH, "0,1");

        //localPlayerWinsLabel
        localPlayerWinsLabel = new JLabel("0");
        panelData.add(localPlayerWinsLabel, "0,0,l,c");
        localPlayerWinsLabel.setFont(new Font("Arial", Font.BOLD, 26));
        localPlayerWinsLabel.setForeground(Color.BLACK);

        //separator
        JSeparator separatorV = new JSeparator(SwingConstants.VERTICAL);
        panelData.add(separatorV, "1,0,1,0");

        //remotePlayerWinsLabel
        remotePlayerWinsLabel = new JLabel("0");
        panelData.add(remotePlayerWinsLabel, "2,0,r,c");
        remotePlayerWinsLabel.setFont(new Font("Arial", Font.BOLD, 26));
        remotePlayerWinsLabel.setForeground(Color.BLACK);


        return panel;
    }


    private JPanel buildGameGridPanel() {

        MouseAdapter gridMouseLisetner = new MouseAdapter() {

            public void mouseClicked(MouseEvent e) {
                if (e.getSource() instanceof TicTacToeGridBox) {
                    if (getGameControl().getPlayersTurn() ==
                            TicTacToeGameControl.LOCAL_PLAYER) {
                        if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
                            LOG.info("BoxClicked : ");
                        }
                        TicTacToeGridBox box = (TicTacToeGridBox) e.getSource();

                        /**
                         * if user hasn't already played this box
                         */
                        if (box.isAvailable()) {
                            box.makeMove(TicTacToeGameControl.LOCAL_PLAYER);
                            box.setAvailable(false);
                            notifyMoveListeners(box);
                        }
                    } else {
                        setTempStatus("Not Your Move!");
                    }
                }
            }
        };

        double b = 5;
        double sizes[][] = {{b, TableLayout.PREFERRED, b, TableLayout.PREFERRED, b, TableLayout.PREFERRED, b},
                {b, TableLayout.PREFERRED, b, TableLayout.PREFERRED, b, TableLayout.PREFERRED, b}};

        TableLayout tbl = new TableLayout(sizes);
        JPanel gridPanel = new JPanel(tbl);

        String rowId = null;
        String colId = null;

        gridPanel.setOpaque(false);
        gridPanel.setBorder(null);


        for (int r = 0; r < this.gridRows; r++) {
            if (r == 0)
                rowId = "A";
            if (r == 1)
                rowId = "B";
            if (r == 2)
                rowId = "C";
            for (int c = 0; c < this.gridColumns; c++) {
                colId = String.valueOf(c);
                TicTacToeGridBox box = new TicTacToeGridBox(rowId + colId, this);

                box.addMouseListener(gridMouseLisetner);
                if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
                    LOG.info("grid [" + r + "] [" + c + "]");
                }
                grid[r][c] = box;
                // LOG.info("these are" + r + "," + c );
                gridPanel.add(box, this.coordinatesToString(r, c));
            }
        }


        return gridPanel;
    }

    private String coordinatesToString(int r, int c) {

        String suffix = null;
        if (r == 0) {

            r = 1;

        } else if (r == 1) {

            r = 3;

        } else if (r == 2) {

            r = 5;

        }
        if (c == 0) {

            c = 1;
            suffix = new String("l,c");

        } else if (c == 1) {

            c = 3;
            suffix = new String("c,c");

        } else if (c == 2) {

            c = 5;
            suffix = new String("r,c");

        }

        String rString = String.valueOf(r);
        String cString = String.valueOf(c);
        LOG.info("String coords " + rString + "," + cString);
        return rString + "," + cString + "," + suffix;

    }

    private JPanel buildGamePanel() {

        double sizes[][] = {{TableLayout.FILL},
                {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}};

        TableLayout tbl = new TableLayout(sizes);
        JPanel panel = new JPanel(tbl);

        panel.setBorder(null);
        panel.setBackground(Color.WHITE);

        panel.add(buildGameStatusPanel(), "0,0,c,c");

        panel.add(buildGameGridPanel(), "0,1,c,c");

        panel.add(buildGameInfoPanel(), "0,2,c,c");

        closeButton = new JButton("Close");
        panel.add(closeButton, "0,3,r,c");
        closeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                destruct();
            }
        });

        return panel;
    }


    protected void showPanel(final String panelName) {


        EventQueue.invokeLater(new Runnable() {

            public void run() {

                cardLayout.show(deckPanel, panelName);

            }
        });
    }

    protected void showConfigPanel(final String panelName) {


        EventQueue.invokeLater(new Runnable() {

            public void run() {

                configCardLayout.show(configDeckPanel, panelName);

            }
        });
    }

    private JPanel buildConfigChooseIconPanel() {


        double sizes[][] = {{TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED},
                {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}};

        TableLayout tbl = new TableLayout(sizes);
        JPanel panel = new JPanel(tbl);
        panel.setBorder(new TitledBorder("Choose Icon"));

        remoteIconLabel = new JLabel(getIconBlank());
        panel.add(remoteIconLabel, "0,0");
        remoteIconLabel.setBorder(new TitledBorder("Remote Player"));

        currentIconLabel = new JLabel(getIconBlank());
        panel.add(currentIconLabel, "1,0");
        currentIconLabel.setBorder(new TitledBorder("Local Player"));

        JLabel labelX = new JLabel(getIconX());
        panel.add(labelX, "0,1");
        labelX.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (getRemotePlayerIconType() != ICON_TYPE_X) {

                    setLocalPlayerIconType(ICON_TYPE_X);
                    setLocalPlayerIcon(getIconX());
                    currentIconLabel.setIcon(getIconX());
                } else {
                    updateMessageLabel("Remote peer chose that icon.");
                }
            }
        });

        JLabel labelO = new JLabel(getIconO());
        panel.add(labelO, "1,1");
        labelO.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (getRemotePlayerIconType() != ICON_TYPE_O) {
                    setLocalPlayerIcon(getIconO());
                    setLocalPlayerIconType(ICON_TYPE_O);
                    currentIconLabel.setIcon(getIconO());
                } else {
                    updateMessageLabel("Remote peer chose that icon.");
                }
            }
        });


        customIconLabel = new JLabel(getIconBlank());
        panel.add(customIconLabel, "2,1");
        customIconLabel.setBorder(new TitledBorder("Custom Icon (Click)"));
        customIconLabel.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {

                localActionCustomIconChosen();

            }
        });


        startGameButton = new JButton("Start Game");
        panel.add(startGameButton, "2,2");
        startGameButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                getGameControl().viewActionConfigured();
            }
        });

        return panel;

    }

    /*
    class BasicImageFilter extends FileFilter {
         public boolean accept(File f) {

             String ext = null;

             String name = f.getName ();

             int extIndex = name.lastIndexOf (".");

             if (extIndex > 0 && extIndex < name.length ()) {

                 ext = name.substring ( extIndex + 1, name.length () -1);
             }



         }

         public String getDescription() {

             return "Basic Image Filter"
         }
    }
    **/
    protected void localActionCustomIconChosen() {

        JFileChooser chooser = new JFileChooser();
        // TODO: use a filefilter
        int returnVal = chooser.showOpenDialog(getRootPane().getParent());

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            long fileSize = file.length();

            LOG.info("localActionCustomIconChoosen " + file.getAbsolutePath() +
                    " " + fileSize);
            if (fileSize > 0L && fileSize <= TicTacToeGameControl.MAX_ICON_SIZE) {
                LOG.info("setting icon ");
                ImageIcon icon1 = new ImageIcon(new ImageIcon(this.gameControl.getFileImage(file.getAbsolutePath())).getImage().getScaledInstance(68,
                        60,
                        Image.SCALE_SMOOTH));
                ImageIcon icon2 = new ImageIcon(new ImageIcon(this.gameControl.getFileImage(file.getAbsolutePath())).getImage().getScaledInstance(68,
                        60,
                        Image.SCALE_SMOOTH));
                ImageIcon icon3 = new ImageIcon(new ImageIcon(this.gameControl.getFileImage(file.getAbsolutePath())).getImage().getScaledInstance(68,
                        60,
                        Image.SCALE_SMOOTH));

                // xxx: chcek for exceptions here
                customIconLabel.setIcon(icon1);
                setLocalPlayerIconType(ICON_TYPE_CUSTOM);
                setLocalPlayerIcon(icon2);
                setLocalPlayerIconFileName(file.getAbsolutePath());
                currentIconLabel.setIcon(icon3);
            }
        }
    }


    protected void localActionPlayAgain() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                playAgainButton.setEnabled(false);
                playAgainButton.setVisible(false);


            }


        });
        updateGameStateView("New Game!");
        this.resetGrid();

        getGameControl().viewActionNewGame();

    }

    protected TicTacToeGameControl getGameControl() {

        return gameControl;

    }

    public void setCurrentPlayersTurn(int player) {

        if (TicTacToeGameControl.REMOTE_PLAYER == player) {

            updatePlayersTurnView(this.remotePlayerName + DISPLAY_REMOTE_PLAYERS_TURN);

        } else if (TicTacToeGameControl.LOCAL_PLAYER == player) {

            updatePlayersTurnView(DISPLAY_LOCAL_PLAYERS_TURN);

        } else if (TicTacToeGameControl.SESSION_ENDED == player) {

            updatePlayersTurnView("");
        }

    }


    public void setRemotePlayerName(String name) {

        this.remotePlayerName = name;

        updateRemotePlayerNameView();
    }

    public void updateRemotePlayerNameView() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {

                remotePlayerNameLabel.setText(remotePlayerName);

            }


        });

    }


    public void setLocalPlayerName(String name) {

        this.remotePlayerName = name;
    }


    private void updateGameStateView(final String stateString) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                gameStateLabel.setText(stateString);
            }
        });
    }

    protected void updatePlayersTurnView(final String stateString) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                playersTurnLabel.setText(stateString);
            }
        });
    }

    public void sessionStateChanged(int sessionState) {

        if (sessionState == TicTacToeGameControl.SESSION_DISCONNECTED) {

            updateGameStateView(DISPLAY_SESSION_TTT_DISCONNECTED);

        } else if (sessionState == TicTacToeGameControl.SESSION_DISCONNECTING) {

            updateGameStateView(DISPLAY_SESSION_TTT_DISCONNECTING);

        } else if (sessionState == TicTacToeGameControl.SESSION_ENDED) {

            updateGameStateView(DISPLAY_SESSION_TTT_ENDED);

        } else if (sessionState == TicTacToeGameControl.SESSION_ENDING) {

            updateGameStateView(DISPLAY_SESSION_TTT_ENDING);

        } else if (sessionState == TicTacToeGameControl.SESSION_STARTED) {

            updateGameStateView(DISPLAY_SESSION_TTT_STARTED);

        } else if (sessionState == TicTacToeGameControl.SESSION_STARTING) {

            updateGameStateView(DISPLAY_SESSION_TTT_STARTING);

        } else if (sessionState == TicTacToeGameControl.SESSION_CONNECTED) {

            updateGameStateView(DISPLAY_SESSION_TTT_CONNECTED);

        } else if (sessionState == TicTacToeGameControl.SESSION_CONNECTING) {

            updateGameStateView(DISPLAY_SESSION_TTT_CONNECTING);

        }

    }


    public void updateRemotePlayerTotalWins(final int wins) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {

                remotePlayerWinsLabel.setText(String.valueOf(wins));

            }
        });

    }

    public void updateLocalPlayerTotalWins(final int wins) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {

                localPlayerWinsLabel.setText(String.valueOf(wins));

            }
        });

    }

    public ImageIcon getIconBlank() {

        return iconBlank;

    }

    public ImageIcon getIconX() {

        return iconX;

    }

    public ImageIcon getIconO() {

        return iconO;

    }

    public void setGameStatus(final String status) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {

                //gameStateLabel.setText (status);

            }
        });
    }


    protected static void displayIncomingGameRequest(String remotePlayerName) {

        JOptionPane.showInternalConfirmDialog(null,
                "Accept game request from " + remotePlayerName,
                "TicTacToe",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE);

    }


    public void setGameDraw() {
        setGameStatus(GAME_DRAW);
        Runnable r = new Runnable() {

            public void run() {
                int i = 0;

                while (i++ < blinkVector) {
                    for (int r = 0; r < gridRows; r++) {
                        for (int c = 0; c < gridColumns; c++) {
                            if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
                                LOG.info("grid [" + r + "] [" + c + "]");
                            }
                            grid[r][c].setBlink();
                        }
                    }
                    try {
                        Thread.sleep(blinkRate);
                    }
                    catch (InterruptedException x) {
                    }
                }
                readyForNextGame();
            }

            {
            }
        };
        blinkGameBoard(r);


    }

    /**
     * the winning set is the remote players winning set
     */
    public void setLocalPlayerLost(final String[] winningSet) {

        if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
            LOG.info("LocalPlayerLost");

        }
        setGameStatus(GAME_LOST);

        updateRemotePlayerTotalWins(this.getGameControl().getRemotePlayerTotalWins());

        Runnable r = new Runnable() {
            public void run() {


                int i = 0;
                while (i++ < blinkVector) {

                    for (int j = 0; j < winningSet.length; j++) {
                        int row = 0;
                        int column = 0;

                        String r = String.valueOf(winningSet[j].charAt(0));
                        if (r.equals("A")) {
                            row = 0;
                        }
                        if (r.equals("B")) {
                            row = 1;
                        }
                        if (r.equals("C")) {
                            row = 2;
                        }

                        String c = String.valueOf(winningSet[j].charAt(1));
                        column = Integer.valueOf(c).intValue();

                        grid[row][column].setBlink();

                    }
                    try {
                        Thread.sleep(blinkRate);
                    } catch (InterruptedException x) {
                        //bleh
                    }
                }

                readyForNextGame();

            }

            ;
        };
        blinkGameBoard(r);


    }


    public void setLocalPlayerWon(final String[] winningSet) {


        updateLocalPlayerTotalWins(this.getGameControl().getLocalPlayerTotalWins());

        setGameStatus(GAME_WON);

        Runnable r = new Runnable() {
            public void run() {


                int i = 0;
                while (i++ < blinkVector) {

                    for (int j = 0; j < winningSet.length; j++) {
                        int row = 0;
                        int column = 0;

                        String r = String.valueOf(winningSet[j].charAt(0));
                        if (r.equals("A")) {
                            row = 0;
                        }
                        if (r.equals("B")) {
                            row = 1;
                        }
                        if (r.equals("C")) {
                            row = 2;
                        }

                        String c = String.valueOf(winningSet[j].charAt(1));
                        column = Integer.valueOf(c).intValue();

                        grid[row][column].setBlink();

                    }
                    try {
                        Thread.sleep(blinkRate);
                    } catch (InterruptedException x) {
                        //bleh
                    }
                }

                readyForNextGame();
            }

            ;
        };
        blinkGameBoard(r);


    }


    /**
     * Threads need to be collected and stopped somehow
     */
    private void blinkGameBoard(Runnable r) {

        Thread t = new Thread(r);
        t.start();

    }

    protected void readyForNextGame() {
        if (isLocallyInitiated()) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    playAgainButton.setEnabled(true);
                    playAgainButton.setVisible(true);
                }
            });
        }
    }


    public String getLocalPlayerIconType() {

        return this.localPlayerIconType;

    }

    public String getRemotePlayerIconType() {

        return this.remotePlayerIconType;

    }

    public void setRemotePlayerIconType(String remotePlayerIconType) {

        this.remotePlayerIconType = remotePlayerIconType;

    }

    public void setLocalPlayerIconType(String localPlayerIconType) {

        this.localPlayerIconType = localPlayerIconType;

    }


    public void setRemotePlayerIcon(ImageIcon icon) {

        remotePlayerIcon = new ImageIcon(icon.getImage().getScaledInstance(68, 68, Image.SCALE_SMOOTH));
        ;

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                remotePlayerIconLabel.setIcon(remotePlayerIcon);
            }
        });


    }

    public void setRemotePlayerIcon(Image image) {

        remotePlayerIcon = new ImageIcon(image);

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                remotePlayerIconLabel.setIcon(remotePlayerIcon);
            }
        });


    }

    public void setTempStatus(final String status) {


        int i = 0;
        while (i++ < blinkVector) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    //gameStateLabel.setText (status);
                }
            });


            try {
                Thread.sleep(blinkRate);
            } catch (InterruptedException x) {
                //bleh
            }


        }


    }

    public void setLocalPlayerIcon(ImageIcon icon) {

        localPlayerIcon = icon;

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                localPlayerIconLabel.setIcon(localPlayerIcon);
            }
        });


    }

    public void addMoveListener(MoveListener l) {
        synchronized (this.moveListeners) {

            moveListeners.add(l);

        }
    }

    private void notifyMoveListeners(TicTacToeGridBox box) {

        Iterator<MoveListener> itr = moveListeners.iterator();

        while (itr.hasNext()) {

            itr.next().localMoveMade(box.getId());
        }

    }


    public ImageIcon getRemotePlayerIcon() {

        return remotePlayerIcon;

    }


    public ImageIcon getLocalPlayerIcon() {

        return localPlayerIcon;

    }

    public void setLocalPlayerIconFileName(String localPlayerIconFileName) {

        this.localPlayerIconFileName = localPlayerIconFileName;

    }

    public String getLocalPlayerIconFileName() {

        return localPlayerIconFileName;

    }

    private void resetGrid() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                for (int r = 0; r < gridRows; r++) {
                    for (int c = 0; c < gridColumns; c++) {
                        grid[r][c].reset();
                    }
                }
            }
        });

    }


    public void remoteMoveMade(String moveId) {

        if (moveId != null) {


            int row = 0;
            int column = 0;

            String r = String.valueOf(moveId.charAt(0));
            if (r.equals("A")) {
                row = 0;
            }
            if (r.equals("B")) {
                row = 1;
            }
            if (r.equals("C")) {
                row = 2;
            }

            String c = String.valueOf(moveId.charAt(1));
            column = Integer.valueOf(c).intValue();

            grid[row][column].makeMove(TicTacToeGameControl.REMOTE_PLAYER);
            grid[row][column].setAvailable(false);

        }
    }


    public boolean isLocallyInitiated() {
        return m_isLocallyInitiated;
    }


}